Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
understudy
Advanced tools
A means to provide interceptors (i.e. hooks) when performing asynchronous actions.
perform
-based actions is asynchronous..perform(action ...
enable hooking.By depending on understudy
you are exposed to four methods: perform
, before
, after
and waterfall
.perform(action, arg0, /* arg1, ... */, work, callback)
This is the core API for invoking hooks provided by Understudy
. Each call to perform
for the same action
should have a consistent argument signature because this is what will be expected by each of the before and after hooks for the action
. The overall flow control is:
before
hooks for action
.work
function for action
.after hooks for
action`.callback
with results from work
function..before(action, arg0, /* arg1, ... */, next)
Called before the work
function is executed in perform with exactly the arguments passed to .perform
. Nothing passed to next
have an impact on the flow control above except any error is supplied short-circuits execution to the callback.
.after(action, arg0, /* arg1, ... */, next)
Called after the work
function is executed in perform with exactly the
arguments passed to .perform
. Nothing passed to next
have an impact on the
flow control above except any error is supplied short-circuits execution to
the callback.
While the above statement is true when using .perform
, after
hooks acquire a
waterfall
like behavior with .waterfall
where the result of work function
gets passed to the after
hooks. Each after hook is then able to mutate the
arguments passed to the next one. Strongly discouraged to change number of
arguments for your user's sanity.
.waterfall(action, arg0, /* arg1, ... */, work, callback)
This is a slightly different perform
that is very useful for when you have to
modify state received from a function in a sequence of configurable hooks.
before
hooks for action
.work
function for action
.after hooks for
actionwith the result returned from the
work`
function.callback
with results from the after
hooks execution (if any) and
otherwise the results from the work
function.Let's consider a real-world application with two interceptable actions:
start
: Application has startedhttp:request
: Application has received an incoming HTTP request.We could easily implement this App
behavior in Understudy
:
var Understudy = require('understudy');
var App = module.exports = function App() {
Understudy.call(this);
};
//
// Starts the application after running before and
// after hooks.
//
App.prototype.start = function (options, callback) {
this.perform('start', options, function (next) {
//
// Here, `options` may have been mutated from the execution
// of the before hooks.
// ...
// Do some other async thing
// ...
// These arguments are passed to the final callback unless
// short-circuited by an error here, or in an after hook.
//
next(null, options);
}, callback);
};
App.prototype.handle = function (req, res) {
req.times = {
start: process.hrtime()
};
this.perform('http:request', req, res, function (next) {
req.times.middle = process.hrtime();
req.times.begin = process.hrtime(req.times.start);
next();
}, function (err) {
if (err) {
//
// Do some error handling.
//
}
req.times.total = process.hrtime(req.times.start);
req.times.after = process.hrtime(req.times.middle);
console.log([
'Total time: %s',
' Before hooks: %s',
' After hooks: %s'
].join('\n'), format(req.times.total), format(req.times.begin), format(req.times.after));
res.end();
});
}
//
// Now we consume a new app with hooks.
//
var http = require('http');
var app = new App();
app.before('start', function (options, next) {
var server = options.server = http.createServer(function (req, res) {
app.handle(req, res);
});
server.listen(options.port, next);
});
app.after('start', function (options, next) {
console.log('App started on %s', options.port);
});
app.before('http:request', function (req, res, next) {
//
// Do something asynchronous.
//
next();
});
app.start({ port: 8080 }, function () {
console.log('ok');
});
//
// Format process.hrtime()
//
function format(s) {
return (s[0] * 1e3 + s[1] / 1e6) / 1e3;
}
Each before
and after
hook can provide an optional error to short-circuit evaluation of the flow that would normally follow it. This error will be provided to your callback
, when supplied. In the event that you DO NOT provide a callback
and a before
, after
or work
function responds with an Error
IT WILL BE IGNORED AND FLOW WILL CONTINUE. e.g.
var Understudy = require('understudy');
var actor = new Understudy();
actor.before('always', function (next) {
next(new Error('I always fail'));
});
actor.after('always', function (next) {
console.log('I always get called. NO MATTER WHAT');
console.log('BUT, only when no callback is supplied.');
next(new Error('Another swallowed error'));
});
actor.perform('always', function (done) {
done(new Error('Errors are ignored here too.'));
});
In other words (as in the above example): if you do not supply a callback to your .perform
then understudy
will consider all of your before
, after
and work
functions as "fire and forget".
FAQs
action interceptor for dynamic extensible systems
The npm package understudy receives a total of 265 weekly downloads. As such, understudy popularity was classified as not popular.
We found that understudy demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.